﻿
using Sykj.ViewModel;
using Sykj.IServices;
using Sykj.Components;
using Sykj.Infrastructure;
using Newtonsoft.Json.Linq;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using System;

namespace Sykj.Web.Api.v1
{
    /// <summary>
    /// 登录/注册/显示  lx
    /// </summary>
    public class WxController : ApiController
    {
        private readonly IUsers _users;
        private readonly IUserMember _userMember;
        private readonly ICacheService _cacheService;
        WxUtils _wxUtils;
        WxJsTicket _wxJsTicket;
        ILogger _logger;

        /// <summary>
        /// 构造方法
        /// </summary>
        /// <param name="users"></param>
        /// <param name="userMember"></param>
        /// <param name="cacheService"></param>
        /// <param name="logger"></param>
        public WxController(IUsers users, IUserMember userMember, ICacheService cacheService, ILogger<WxController> logger)
        {
            _cacheService = cacheService;
            _users = users;
            _userMember = userMember;
            _wxUtils = new WxUtils(_cacheService);
            _wxJsTicket = new WxJsTicket(_cacheService);
            _logger = logger;
        }

        #region 微信小程序获取腾讯unionId 

        /// <summary>
        /// 微信小程序获取腾讯unionId lx
        /// </summary>
        /// <param name="code">code</param>
        /// <param name="encryptedData">encryptedData</param>
        /// <param name="iv">iv</param>
        /// <returns></returns>
        [HttpPost("getunionid")]
        public ApiResult GetUnionId(string code, string encryptedData, string iv)
        {
            if (string.IsNullOrWhiteSpace(code) ||
                string.IsNullOrWhiteSpace(encryptedData) ||
                string.IsNullOrWhiteSpace(iv))
            {
                return Failed("参数输入不完整！");
            }
            //通过code获取小程序openid与sessionkey
            string jsonStr = _wxUtils.GetXcxKey(code);
            JObject json = JObject.Parse(jsonStr);

            string openid = json["openid"].ToString();
            string session_key = json["session_key"].ToString();
            //解密获取手机号
            string strJm = AESEncrypt.Decrypt(encryptedData, session_key, iv);
            if (string.IsNullOrWhiteSpace(strJm))
            {
                return Failed("认证解密失败！");
            }

            JObject jsonUser = JObject.Parse(strJm);
            // string phone = jsonUser["phoneNumber"].ToString();
            string unionId = jsonUser["unionId"].ToString();
            if (string.IsNullOrWhiteSpace(unionId))
            {
                return Failed("获取unionId失败！");
            }

            var model = new Entity.Users();
            if (_users.IsExistsUnionId(unionId))
            {

                //通过手机号，查询用户信息返回
                model = _users.GetModel(c => c.UnionId == unionId);
                if (openid != null)
                {
                    model.WechatOpenId = openid;
                    _users.Update<Entity.Users>(model, true, x => x.WechatOpenId);
                }
                //Token码
                if (model.UserType != "UU")
                {
                    return Failed("用户未授权！");
                }
                var tm = new TokenModel()
                {
                    Uid = model.UserId.ToString(),
                    UserName = model.UserName,
                    Role = "UU",
                    Project = "App",
                    TokenType = "App"
                };
                dynamic data = new System.Dynamic.ExpandoObject();
                data.Token = JwtHelper.IssueJWT(tm);//授权认证
                data.phone = model.UserName;//手机号
                return DataResult(data);
            }
            else
            {
                JObject jsonResult = new JObject();
                jsonResult.Add("phone", "");
                jsonResult.Add("unionId", unionId);
                return DataResult(jsonResult);
            }
        }

        #endregion

        #region 微信小程序用户注册

        /// <summary>
        /// 用户注册 lx
        /// </summary>
        /// <param name="code">参数</param>
        /// <param name="encryptedData">参数</param>
        /// <param name="iv">参数</param>
        /// <param name="nickName">用户昵称</param>
        /// <param name="avatarUrl">用户头像</param>
        /// <param name="unionId">参数unionId</param>
        /// <param name="inviteUserId">邀请人id</param>
        /// <returns></returns>
        [HttpPost("register")]
        public ApiResult Register(string code, string encryptedData, string iv, string nickName = "", string avatarUrl = "", string unionId = "", int inviteUserId = 0)
        {
            if (string.IsNullOrWhiteSpace(code) ||
               string.IsNullOrWhiteSpace(encryptedData) ||
               string.IsNullOrWhiteSpace(iv))
            {
                return Failed("参数输入不完整！");
            }
            //通过code获取小程序openid与sessionkey
            string jsonStr = _wxUtils.GetXcxKey(code);
            JObject json = JObject.Parse(jsonStr);

            string openid = json["openid"].ToString();
            string session_key = json["session_key"].ToString();
            //解密获取手机号
            string strJm = AESEncrypt.Decrypt(encryptedData, session_key, iv);

            if (string.IsNullOrWhiteSpace(strJm))
            {
                return Failed("解密数据失败！");
            }

            JObject jsonUser = JObject.Parse(strJm);
            string phone = jsonUser["phoneNumber"].ToString();

            if (string.IsNullOrWhiteSpace(phone))
            {
                return Failed("手机号获取失败！");
            }

            var model = new Entity.Users();
            if (_users.IsExists(phone))
            {
                //如果该手机号存在，则绑定UnionId
                model = _users.GetModel(c => c.UserName == phone);
                if (string.IsNullOrWhiteSpace(model.WechatOpenId) || string.IsNullOrWhiteSpace(model.UnionId))
                {
                    model.WechatOpenId = openid;
                    model.UnionId = unionId;
                    model.NickName = nickName;
                    model.Gravatar = avatarUrl;
                    model.UserType = "UU";
                    _users.Update<Entity.Users>(model, true, x => x.WechatOpenId, x => x.UnionId, x => x.NickName, x => x.Gravatar);
                }
            }
            else
            {
                //不存在则新增用户
                model.UserId = _userMember.Register(phone, "", nickName, openid, unionId, avatarUrl, inviteUserId);
            }
            var tm = new TokenModel()
            {
                Uid = model.UserId.ToString(),
                UserName = phone,
                Role = "UU",
                Project = "App",
                TokenType = "App"
            };

            dynamic data = new System.Dynamic.ExpandoObject();
            data.Token = JwtHelper.IssueJWT(tm);
            data.phone = phone;
            return DataResult(data);
        }

        #endregion

        #region 微信app登录

        /// <summary>
        /// 微信app登录 bjg
        /// </summary>
        /// <param name="unionId">腾讯唯一标识</param>
        /// <returns></returns>
        [HttpPost("loginunionid")]
        public ApiResult LoginUnionid(string unionId)
        {
            if (string.IsNullOrWhiteSpace(unionId))
            {
                return Failed("unionId不能为空");
            }
            var model = _users.GetModel(x => x.UnionId == unionId);
            if (model != null)
            {
                var tm = new TokenModel()
                {
                    Uid = model.UserId.ToString(),
                    UserName = model.UserName,
                    Role = "UU",
                    Project = "App",
                    TokenType = "App"
                };
                dynamic data = new System.Dynamic.ExpandoObject();
                data.Token = JwtHelper.IssueJWT(tm);//授权认证
                data.phone = model.UserName;//手机号
                return DataResult(data);
            }
            else
            {
                JObject jsonResult = new JObject();
                jsonResult.Add("phone", "");
                jsonResult.Add("unionId", unionId);
                return DataResult(jsonResult);
            }
        }

        #endregion

        #region 微信app用户注册绑定 

        /// <summary>
        /// 微信app用户注册绑定 lx
        /// </summary>
        /// <param name="phone">用户手机号</param>
        /// <param name="code">短信验证码</param>
        /// <param name="nickName">用户昵称</param>
        /// <param name="avatarUrl">用户头像</param>
        /// <param name="unionId">参数unionId</param>
        /// <param name="cId">设备ID</param>
        /// <returns></returns>
        [HttpPost("userbind")]
        public ApiResult UserBind(string phone, string code, string nickName = "", string avatarUrl = "", string unionId = "", string cId = "")
        {
            if (string.IsNullOrWhiteSpace(phone) ||
               string.IsNullOrWhiteSpace(nickName) ||
               string.IsNullOrWhiteSpace(unionId))
            {
                return Failed("参数输入不完整！");
            }
            if (!phone.IsMobile())
            {
                return Failed("手机号码格式错误！");
            }

            //验证码
            if (string.IsNullOrWhiteSpace(code))
            {
                return Failed("验证码不能为空！");
            }
            string key = phone + "WXSMSCode";
            var obj = _cacheService.GetCache<string>(key);
            if (obj == null)
            {
                return Failed("验证码异常！");
            }
            if (obj.ToString() != code)
            {
                return Failed("验证码错误！");
            }

            var model = new Sykj.Entity.Users();
            if (_users.IsExists(phone))
            {
                //如果该手机号存在，则绑定UnionId
                model = _users.GetModel(c => c.UserName == phone);
                if (string.IsNullOrWhiteSpace(model.WechatOpenId) || string.IsNullOrWhiteSpace(model.UnionId))
                {
                    model.UnionId = unionId;
                    model.NickName = nickName;
                    model.Gravatar = avatarUrl;
                    _users.Update<Entity.Users>(model, true, x => x.UnionId, x => x.NickName, x => x.Gravatar);
                }
            }
            else
            {
                //不存在则新增用户
                model.UserId = _userMember.Register(phone, "123456", nickName, "", unionId, avatarUrl);
            }
            var tm = new TokenModel()
            {
                Uid = model.UserId.ToString(),
                UserName = phone,
                Role = "UU",
                Project = "App",
                TokenType = "App"
            };
            if (!string.IsNullOrWhiteSpace(cId))
            {
                PushService pushService = Factory.CreatePushService();
                if (pushService != null)
                {
                    pushService.BindAlias(cId, tm.Uid);
                }
            }
            dynamic data = new System.Dynamic.ExpandoObject();
            data.Token = JwtHelper.IssueJWT(tm);
            data.phone = phone;
            return DataResult(data);
        }

        /// <summary>
        /// app发送绑定微信用户短信 lx
        /// </summary>
        /// <param name="phone">手机号</param>
        /// <param name="validateCode">验证码</param>
        /// <param name="sessionKey">会话key</param>
        /// <returns></returns>
        [HttpPost("sendsms")]
        public ApiResult SendSms(string phone, string validateCode, string sessionKey)
        {
            if (string.IsNullOrWhiteSpace(phone))
            {
                return Failed("手机号不能为空");
            }
            if (string.IsNullOrWhiteSpace(phone))
            {
                return Failed("验证码不能为空");
            }
            var bl = _users.IsExist(x => x.UserName == phone && !string.IsNullOrWhiteSpace(x.UnionId));
            if (bl)
            {
                return Failed("该手机号已经被绑定，请核对！");
            }
            string code = _cacheService.GetCache<string>(sessionKey);
            if (code == null)
            {
                return Failed("请输入图片验证码！");
            }
            if (validateCode.ToLower() != code.ToLower())
            {
                return Failed("图片验证码输入错误！");
            }

            Random rnd = new Random();
            int rand = rnd.Next(1000, 9999);
            string msg = string.Empty;
            //短信模板
            string content = string.Format(BaseConfig.GetValue("SMS_Content"), rand);

            ISmsServer smsServer = Factory.CreateSmsServer();
            bool b = smsServer.SendMsg(phone, content, ref msg);
            if (b)
            {
                string key = phone + "WXSMSCode";
                //存缓存
                _cacheService.SetCache(key, rand.ToString(), DateTime.Now.AddMinutes(2));
                _cacheService.RemoveCache(sessionKey);
                return Success("短信发送成功，请注意查收！");
            }
            else
            {
                return Failed("短信发送失败，原因:" + msg);
            }
        }
        #endregion

        #region 微信服务号

        /// <summary>
        /// 跳转到微信登录url lx
        /// </summary>
        /// <param name="returnUrl">跳转返回URL</param>
        /// <returns></returns>
        [HttpGet("wxloginurl")]
        public IActionResult WxLoginUrl(string returnUrl)
        {
            WxUtils wxUtils = new WxUtils();
            string url = wxUtils.CreateOauthUrlForCode(BaseConfig.ApiDoMain + "/api/v1/wx/callback", false, returnUrl);
            //_logger.LogError("returnUrl:" + returnUrl);
            return Redirect(url);
        }

        /// <summary>
        /// 微信登录后跳转回URL lx
        /// </summary>
        /// <returns></returns>
        [HttpGet("callback")]
        public IActionResult CallBack()
        {
            WxUtils wxUtils = new WxUtils();
            string strCode = Request.Query["code"];
            string sp = Request.Query["state"];
            string openid = wxUtils.GetOpenId(strCode);
            //_logger.LogError("open:"+openid);
            if (!string.IsNullOrWhiteSpace(openid))
            {
                HttpContext.Session.SetString(Constant.WXFWOPENID, openid);
                //_logger.LogError("sp:" + sp);
                return Redirect(sp);
            }
            else
            {
                return Content("微信请求失败！");
            }
        }

        /// <summary>
        /// 判断微信服务号是否登录 lx
        /// </summary>
        /// <returns></returns>
        [HttpGet("iswxdylogin")]
        public IActionResult IsWxFwLogin()
        {
            if (string.IsNullOrWhiteSpace(HttpContext.Session.GetString(Constant.WXFWOPENID)))
            {
                return Json(AjaxResult(false));
            }
            else
            {
                return Json(AjaxResult(true));
            }
        }

        /// <summary>
        /// 微信公众号配置 lx
        /// </summary>
        /// <param name="url">当前url</param>
        /// <returns></returns>
        [HttpGet("wxconfig")]
        public ApiResult WxConfig(string url)
        {
            if (string.IsNullOrWhiteSpace(url))
            {
                return Failed("请输入url");
            }
            JObject jsonData = new JObject();
            jsonData.Add("appId", BaseConfig.GetValue(Constant.WECHATFWAPPID));
            jsonData.Add("timestamp", _wxJsTicket.Timestamp);
            jsonData.Add("nonceStr", _wxJsTicket.Noncestr);
            jsonData.Add("signature", _wxJsTicket.GetSignature(url));
            return DataResult(jsonData);
        }
        #endregion

        #region 微信pc认证

        /// <summary>
        /// 跳转到微信登录url lx
        /// </summary>
        /// <param name="returnUrl">跳转返回URL</param>
        /// <returns></returns>
        [HttpGet("wxpcloginurl")]
        public IActionResult WxPcLoginUrl(string returnUrl)
        {
            WxUtils wxUtils = new WxUtils();
            string url = wxUtils.CreatePcOauthUrlForCode(BaseConfig.DoMain + "/api/v1/wx/callbackpc", returnUrl);
            return Redirect(url);
        }

        /// <summary>
        /// 微信登录后跳转回URL lx
        /// </summary>
        /// <returns></returns>
        [HttpGet("callbackpc")]
        public IActionResult CallBackPc()
        {
            WxUtils wxUtils = new WxUtils();
            string strCode = Request.Query["code"];
            string sp = Request.Query["state"];
            string unionId = wxUtils.GetPcUnionid(strCode);

            if (string.IsNullOrWhiteSpace(unionId))
            {
                return Content("微信解码失败");
            }

            //1.通过unionid查找用户
            var model = _users.GetModel(x => x.UnionId == unionId);
            if (model != null)
            {
                //2.用户在，登录成功,获取jwt token返回,
                if (model.UserType != "UU")
                {
                    return Content("用户未授权！");
                }
                var tm = new TokenModel()
                {
                    Uid = model.UserId.ToString(),
                    UserName = model.UserName,
                    Role = "UU",
                    Project = "App",
                    TokenType = "App"
                };
                string token = JwtHelper.IssueJWT(tm);//授权认证
                return Redirect(sp + "?token=" + token);
            }
            else
            {
                //3.如果不存在，则调整到用户绑定页面  
                return Redirect(BaseConfig.DoMain + "/web/weixin_binding.html?unionId=" + unionId);
            }
        }

        /// <summary>
        /// 微信Pc用户注册绑定 lx
        /// </summary>
        /// <param name="phone">用户手机号</param>
        /// <param name="code">短信验证码</param>
        /// <param name="unionId">unionId</param>
        /// <returns></returns>
        [HttpPost("userbindpc")]
        public ApiResult UserBindPc(string phone, string code, string unionId)
        {
            if (string.IsNullOrWhiteSpace(phone) ||
               string.IsNullOrWhiteSpace(code) || string.IsNullOrWhiteSpace(unionId))
            {
                return Failed("参数输入不完整！");
            }
            if (!phone.IsMobile())
            {
                return Failed("手机号码格式错误！");
            }
            //验证码
            if (string.IsNullOrWhiteSpace(code))
            {
                return Failed("验证码不能为空！");
            }
            string key = phone + "WXPCSMSCode";
            var obj = _cacheService.GetCache<string>(key);
            if (obj == null)
            {
                return Failed("验证码异常！");
            }
            if (obj.ToString() != code)
            {
                return Failed("验证码错误！");
            }

            var model = new Sykj.Entity.Users();
            if (string.IsNullOrWhiteSpace(unionId))
            {
                return Failed("获取unionId失败！");
            }
            if (_users.IsExists(phone))
            {
                //如果该手机号存在，则绑定UnionId
                model = _users.GetModel(c => c.UserName == phone);
                if (string.IsNullOrWhiteSpace(model.WechatOpenId) || string.IsNullOrWhiteSpace(model.UnionId))
                {
                    model.UnionId = unionId;
                    _users.Update<Entity.Users>(model, true, x => x.UnionId);
                }
            }
            else
            {
                //不存在则新增用户
                model.UserId = _userMember.Register(phone, "123456", "", "", unionId, "");
            }
            var tm = new TokenModel()
            {
                Uid = model.UserId.ToString(),
                UserName = phone,
                Role = "UU",
                Project = "App",
                TokenType = "App"
            };
            dynamic data = new System.Dynamic.ExpandoObject();
            data.Token = JwtHelper.IssueJWT(tm);
            data.phone = phone;
            return DataResult(data);
        }

        /// <summary>
        /// app发送绑定微信用户短信 lx
        /// </summary>
        /// <param name="phone">手机号</param>
        /// <param name="validateCode">验证码</param>
        /// <param name="sessionKey">会话key</param>
        /// <returns></returns>
        [HttpPost("sendsmspc")]
        public ApiResult SendSmsPc(string phone, string validateCode, string sessionKey)
        {
            if (string.IsNullOrWhiteSpace(phone))
            {
                return Failed("手机号不能为空");
            }
            if (string.IsNullOrWhiteSpace(phone))
            {
                return Failed("验证码不能为空");
            }
            if (_users.IsExists(phone))
            {
                return Failed("该手机号已经被注册!");
            }
            string code = _cacheService.GetCache<string>(sessionKey);
            if (code == null)
            {
                return Failed("请输入图片验证码！");
            }
            if (validateCode.ToLower() != code.ToLower())
            {
                return Failed("图片验证码输入错误！");
            }

            Random rnd = new Random();
            int rand = rnd.Next(1000, 9999);
            string msg = string.Empty;
            //短信模板
            string content = string.Format(BaseConfig.GetValue("SMS_Content"), rand);

            ISmsServer smsServer = Factory.CreateSmsServer();
            bool b = smsServer.SendMsg(phone, content, ref msg);
            if (b)
            {
                string key = phone + "WXPCSMSCode";
                //存缓存
                _cacheService.SetCache(key, rand.ToString(), DateTime.Now.AddMinutes(2));
                _cacheService.RemoveCache(sessionKey);
                return Success("短信发送成功，请注意查收！");
            }
            else
            {
                return Failed("短信发送失败，原因:" + msg);
            }
        }
        #endregion
    }
}